#-*- coding: utf-8 -*-
#===============================================================================
# IMPORTS
#===============================================================================
'''
Created on 7 déc. 2013

@author: Goz
'''
#à placer quelque part => dans un autre modele ?? apistatus => DOIS CREER UN MODEL DE TYPE API_STATUS
#retourne les top elements (current time, cachedUntil root len)

from __future__ import unicode_literals

import os
import traceback
import urllib
import urllib2

from dateutil import parser
from django.db import models
from django.utils.timezone import utc

from apiManager.models import *
import datetime as DT
from eve_scm import settings
import xml.etree.ElementTree as ET


def apiMetadata(self,root, accountID, apiName):
#      print "nb in root: ", len(root)
    currentTime = root[0].text
    cachedUntil = root[2].text
    #assetStatus = Api.objects.create_apiStatus('AssetList', currentTime, cachedUntil)
    #BUG ICI : probleme pour appeler l'autre classe apiStatus ici
    #MANQUE REF VERS ACCOUNT
    #apiStatus = ApiStatus.objects.db_manager('eve_scm').create_apiStatus('AssetList', currentTime, cachedUntil)
    apiStatus = Api.create_apiStatus(self, accountID, apiName, currentTime, cachedUntil)
    #apiStatus = AssetManager.objects.create_apiStatus('AssetList', currentTime, cachedUntil)
    metadata = [currentTime, cachedUntil, apiStatus]
    return metadata
        
#   print "Current time: ", root[0].text
#   print "CachedUntil: ", root[2].text
    #renvoyer une liste avec ces valeurs







#===========================================================================
#Asset Parser 
#===========================================================================
# 1ere fonction récupère root        # A MODIFIER UTILISER APINAME (LINKED WITH ACCOUNT)
# 2ème fonction récupère api meta data        
# 3ème fonction récupère 1er rowset        
# 4ème fonction récupère les rows et les save        
# commet object de modèle        
# Pour les assets iteration en plus en 3        


    #iter dans un noeud d'un ElementTree suivant un path (récupère les noeuds correspondants au path) et 
    #retourne un dictionnaire avec pour (key) les noeuds parent et pour (valeurs) la liste des noeuds enfants (ElementTree)
def parse_subrow(self, node, path):
#         self.node = node
#         self.path = path
    childsList = list(node.iterfind(path))
    for child in childsList:
            #print child itemID :
            print "    -------- : {} ".format(child.get('itemID'))
    #childsList = list(node.iterfind("./rowset/row"))
    parent_map = {node.get('itemID') : childsList}
    #print parent_map
    return parent_map

#prend un dictionnaire et explore pour chaque key (parent) les enfants (noeuds) qui correspondent à un path
#iter de boucle en boucle (doit couvrir toutes les possibles x sub-level d'un xml)
def parcours_map(self, parent_childs_Map, path):
    y=0
    reflv=[]
    espace = "    "
    for cle, valeurs in parent_childs_Map.items():
        #print cle : nb subitems - subitems
        #print "{} : {} - {}".format(cle,len(valeurs), valeurs)
        for subitem in valeurs:
            y+=1
            if subitem is not None:
                #subitem = enfant
                #reflv fonctionne pas correctement => faudrait le passer d'une fonction à l'autre  ou a mettre dans parse_subrow??? 
                reflv.append(1)
                #1er lv sub item
                #print nb - itemID : nb subitems - list subitems
                print "        {} - {} : {} - {}".format( y, subitem.get('itemID'), len(list(subitem.iterfind('./rowset/row'))), list(subitem.iterfind('./rowset/row')))
                subAsset = Asset.objects.create_asset(subitem.get('itemID'), cle , subitem.get('locationID'), subitem.get('typeID'), subitem.get('quantity'), subitem.get('flag'), subitem.get('singleton'), subitem.get('rawQuantity'))
                #print reflv - subitems saved
                print "           sub Asset {} saved in database".format( subitem.get('itemID'))
                #Fin premier lv parents - enfants
#_------------------------------------------------------------------------------------------------------------------------------------------
                
                
                #test si les enfants ont un ou des enfants
                if len(list(subitem.iterfind('./rowset/row'))) > 1:
                    print "        sub item has child"
                    sub_map = self.parse_subrow(subitem, './rowset/row')
                    self.parcours_map(sub_map, '/rowset/row')
                else:
                    print "        sub item has NO child"
            else:
                print "        sub item is NONE"
                    
                
#===========================================================================
# TO DO => remplacer si ça marche les path en dur avec le path var
#===========================================================================
# fonction qui parcourt tous les noeuds avec comme tag "sutbag" contenus dans "node" dont les parents sont des noeuds qui ont un attribut "attribute" qui vaut "attributeValue"
#récupère les premiers noeud d'un ElementTree correspondant à un path (ici stations/primary containers)
#node = à root du xml, path = tous les row(tag) qui possèdent l'attribut "locationID"
def parse_row(self, node, attributeName, tag):
    y=0
    #rowCount=0
#         self.node = node
    control= True
    #ça c'est juste! ça prendra que les premiers noeuds!
    #node.iterfind(".//*[@name='assets']/row") => tous les noeud row qui sont enfants de noeuds ayant comme attribut "name" = "assets" => Ok 1 seul niveau donc ça marche   
    #A modifier pour prendre les row qui possèdent l'attribut "locationID" (plus simple) => récupère toutes les stations / conteneurs primaires
    try:
        if node is not None:
            #path = ".//{0}[@{1}]".format(tag, attributeName)
            path = ".//row[@{}]".format(attributeName)
            rows = node.iterfind(path)
            print "Nombre de row : ", len(list(node.findall(path)))
            while control:
                try:
                    #a t on tj besoin de cette condition ( test déjà fait plus haut)
                    if rows is not None:
                        y+=1
                        #rowCount += 1
                        #print "                    ", y , "- ROW COUNT : ", rowCount 
                        #parcours l'iterateur d'un cran de plus (passe à l'element suivant)
                        element = rows.next()
                        if element is not None:
                            #print nb - Item : itemID :
                            print "{} - Item : {} :".format(y, element.get('itemID'))
                            asset = Asset.objects.create_asset(element.get('itemID'), node.get('itemID'), element.get('locationID'), element.get('typeID'), element.get('quantity'), element.get('flag'), element.get('singleton'), element.get('rawQuantity'))
                            #facultatif
                            asset.save()
                            print "Primary Asset {} saved in database".format(element.get('itemID'))
                            if len(list(element.iter('row'))) > 1:
                                print"subitem has child :"
                                parent_map = self.parse_subrow(element, './rowset/row')
                                #print "Map : ", parent_map
                                self.parcours_map(parent_map, './rowset/row')
                            else:
                                print " subitem has no child"
                        else:
                            print "element is NONE"
                except StopIteration:
                    print "Stop iteration : no more element"
                    control = False       
    except Exception , err:
            print traceback.format_exc()
    #return self
                
    
#appelle la mise a jour des donnees de l'api
def refreshAssets(self):
    #xml file sur ordi portable
    start_time = DT.datetime.now()
    xmlFile = 'c:/wamp/www/eve_api_test/AssetList_2.xml'
    #xml file sur ordi fixe
    #xmlFile = 'g:/Users/Goz/Dropbox/Eve Online/Dj-pses/eve_api_test/AssetList_2.xml'
    try:
        root = self.catchAssetsApiFile(xmlFile)
        #recupere tous les anciens assets dans la base 
        allAssets = Asset.objects.all()
        #efface toutes les entrees
        allAssets.delete()
        #parse le xml de l'api
        #parse_row(root, 
        self.parse_row(root, 'locationID', 'row')
        #enregistre le status de l'api dans la base apiStatus
        #ApiStatus.objects.db_manager(using).apiMetadata(root)
        self.apiMetadata(root)
        
        
    except Exception, e:
        print e 
    end_time = DT.datetime.now()
    tdelta = end_time - start_time    
    print "refresh done in {} seconds => {} assets in database".format(tdelta.total_seconds(), len(Asset.objects.all()))
    #return self
    
    

    
    
#appelle la mise a jour des donnees de l'api
def refreshApi(self, ApiName):
    start_time = DT.datetime.now()
    #apiNames = ['Asset List', 'Account Balances', 'Corporation Sheet', 'Industry Jobs', 'Market Orders', 
    #         'StarbaseDetail Details (POS)', 'Starbase List (POS)',
    #        'Wallet Journal' ,'Wallet Transactions']
    #fonction de choix qui retournent tous les path pour une Api donnee afin de parser correctement leur arbre xml respectifs 
#     def assetList(self):
#         try:
#             #xml file sur ordi portable
#             xmlFile = 'c:/wamp/www/eve_api_test/AssetList_2.xml'
#             rowsetName1 = 'assets'
#             rowsetName2 = 'contents'
#             #xml file sur ordi fixe
#             #xmlFile = 'g:/Users/Goz/Dropbox/Eve Online/Dj-pses/eve_api_test/AssetList_2.xml'
#             assetPath1 = ['locationID', 'row']
#             #récup tous les noeuds row qui ont l'attributName      
#           #  assetPath2 =  ".//row[@{}]".format(attributeName)
#             assetPath3 = []
#             classe = Asset      
#            # assetInfos  = [xmlFile, assetPath1, assetPath2, assetPath3,  classe] 
#             #delete all olds assets 
#             Asset.objects.all().delete()                 
#         except Exception, err:
#             print  traceback.format_exc()
#              
#         return assetInfos
    
    def walletTrans(self):
        transactionsPath = ['row']
        return transactionsPath
    
    def walletJour(self):
        journalPath = ['row']
        return journalPath

    def industry(self):
        industryPath = ['row']
        return industryPath
    
    def balance(self):
        balancePath = ['row']
        return balancePath

    def corpSheet(self):
        corpSheetPath = ['row']
        return corpSheetPath
    
    def orders(self):
        ordersPath = ['row']
        return ordersPath
    
    def posDetail(self):
        posDetailPath = ['row']
        return posDetailPath
    
    def posList(self):
        posListPath = ['row']
        return posListPath
            
    #pathFunctions = { 'Asset List' : assetList , 'Account Balance' : balance, 'Corporation Sheet' : corpSheet, 'Industry Jobs' : industry, 
#                      'Market Orders' : orders, 'StarbaseDetail Details (POS)': posDetail, 'Starbase List (POS)' : posList, 'Wallet Journal' : walletJour, 
#                      'Wallet Transactions' : walletTrans,  
#                      } # dict qui map les choix d'un switch avec la fonction que l'on veut executer en fonction du choix. 
#     
#     xmlFile = pathFunctions[ApiName]()[0]
#     path1 = pathFunctions[ApiName]()[1]
#     path2 = pathFunctions[ApiName]()[2]
#     path3 = pathFunctions[ApiName]()[3]
#     classe = pathFunctions[ApiName]()[4]
    
    #SOIT TOUT FAIRE DANS LE DICT-SWITCH ? => FAUDRAIT APPELER LA CLASSE LIEE AU APINAME / SI C'EST 'ASSET LIST' EN PARAM => CREE AUTO DES ASSETS
    
#     try:
#         root = self.catchApiFile(xmlFile) 
#         #parse le xml de l'api
#         self.parse_row(root, 'locationID', 'row')
#         #enregistre le status de l'api dans la base apiStatus
#         #ApiStatus.objects.db_manager(using).apiMetadata(root)
#         self.apiMetadata(root)
        
        
#     except Exception, e:
#         print e 
    end_time = DT.datetime.now()
    tdelta = end_time - start_time    
    print "refresh done in {} seconds => {} assets in database".format(tdelta.total_seconds(), len(Asset.objects.all()))
    #return self